<?php
namespace App\Models\ActivityInfo;

use App\Contracts\Repositories\ActivityInfoRepository as Activities;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class ActivityInfoService
{
    /**
     * @var Activities
     */
    private $activities;

    public function __construct(Activities $activities)
    {
        $this->activities = $activities;
    }

    /**
     * @param $activity
     * @return mixed
     */
    public function createActivity($activity)
    {
        return $this->activities->create($activity);
    }

    /**
     * @param $activity
     * @param $conditions
     * @return mixed
     */
    public function modifyActivity($activity, $conditions)
    {
        return $this->activities->modify($activity, $conditions);
    }

    public function updateActivityPrize($activityId, $prizeId)
    {
        return $this->activities->updateActivityPrize($activityId, $prizeId);
    }

    /**
     * @param $conditions
     * @param bool $softDeletion
     * @return mixed
     */
    public function deleteActivity($conditions, $softDeletion = true)
    {
        return $this->activities->delete($conditions, $softDeletion);
    }

    /**
     * 统计活动奖品使用信息
     * @param $activityId
     * @return array
     */
    public function settleActivity($activityId)
    {
        $activityInfo = $this->activities->findById($activityId);
        Log::info($activityInfo);
        foreach ($activityInfo['activity_record'] as $activityRecord) {
            if (!isset($number[$activityRecord['prize_id']])) {
                $number[$activityRecord['prize_id']] = 0;
            }
            if (!isset($amount[$activityRecord['prize_id']])) {
                $amount[$activityRecord['prize_id']] = 0;
            }
            $number[$activityRecord['prize_id']] += $activityRecord['number'];
            $amount[$activityRecord['prize_id']] += $activityRecord['amount'];
        }
        $summary = array_column($activityInfo['prize_record'], 'summary', 'prize_id');
        foreach ($activityInfo['prize_record'] as $prizeRecord) {
            $prizeRecords[] = array(
                'prize_id' => $prizeRecord['prize_id'],
                'number' => $prizeRecord['number'] - $number[$prizeRecord['prize_id']],
                'summary' => $prizeRecord['summary'] - $amount[$prizeRecord['prize_id']]
            );
        }
        $this->activities->updateActivityPrize($prizeRecords);
        $result = array(
            'number' => $activityInfo['number'],
            'amount' => $activityInfo['summary'],
            'used_number' => $number,
            'used_amount' => $amount,
            'remain_number' => $activityInfo['number'] - $number,
            'remain_amount' => $activityInfo['summary'] - $amount
        );
        $this->activities->delete(array('id' => $activityId), true);

        return $result;
    }

    /**
     * 计算中奖结果
     * @param $activityId
     * @param $prizeId
     * @param $activityRecordService
     * @param $storageService
     * @param $csvReaderService
     * @return array
     */
    public function destributeActivity($activityId, $prizeId, $activityRecordService, $storageService, $csvReaderService)
    {
        $prizeInfo = $this->activities->getPrizeInfo($prizeId);
        if ($prizeInfo['type_code'] == 'coupon') {
            switch ($prizeInfo['voucher_type']) {
                case 0:
                    break;
                case 1:
                    if (!Cache::has('unifiedActivityRecordCount')) {
                        $activityRecordCount = $activityRecordService->count([['prize_id' , $prizeId], ['activity_id', $activityId]]);
                        Cache::forever('unifiedActivityRecordCount', $activityRecordCount);
                    }
                    $activityRecordCount = Cache::get('unifiedActivityRecordCount');
                    $voucherCode = $prizeInfo['voucher_code'];
                    $numberLength = strlen(strval($prizeInfo['stock_number']));
                    $newCode = str_pad($activityRecordCount, $numberLength, '0', STR_PAD_LEFT);
                    $prizeInfo['voucher_code'] = $voucherCode . $newCode;
                    Cache::forever('unifiedActivityRecordCount', $activityRecordCount + 1);
                    break;
                case 2:
                    if (!Cache::has('customActivityRecordCount')) {
                        $activityRecordCount = $activityRecordService->count([['prize_id', $prizeId], ['activity_id', $activityId]]);
                        Cache::forever('customActivityRecordCount', $activityRecordCount);
                    }
                    $activityRecordCount = Cache::get('customActivityRecordCount');
                    $csvReaderService->set_csv_file($storageService->tomedia($prizeInfo['voucher_link']));
                    $prizeInfo['voucher_code'] = $csvReaderService->get_data($activityRecordCount);
                    Cache::forever('customActivityRecordCount', $activityRecordCount + 1);
                    break;
            }
        }
        return $prizeInfo;
    }

    /**
     * 计算中奖结果
     * @param $activityId
     * @param null $prizeId
     * @return array
     */
    public function destributeActivity_back($activityId, $prizeId = null)
    {
        $activityInfo = $this->activities->findById($activityId);
        if (!$prizeId) {
            //奖品中奖比例
            $prizePercents = array_column($activityInfo['prize_record'], 'probability', 'prize_id');
            //获取抽中的奖品ID
            $prizeId = $this->randomPrize($prizePercents);
        }
        //奖品类型
        $typeCodes = array_column($activityInfo['prize'], 'type_code', 'id');
        //活动已中奖信息
        $prizeRecordAmount = 0;
        foreach ($activityInfo['activity_record'] as $activityRecord) {
            if ($activityRecord['prize_id'] != $prizeId) {
                continue;
            }
            //            $prizeRecordNumber += $activityRecord['number'];//已中奖个数
            $prizeRecordAmount += $activityRecord['amount'];//已中奖总额，红包是金额，其他是个数
        }
        foreach ($activityInfo['prize_record'] as $prizeRecord) {
            if ($prizeRecord['prize_id'] == $prizeId && $prizeRecord['operate'] == 'delivery') {
                $prizeSettings = $prizeRecord;
                break;
            }
        }
        //还有剩余，计算中奖结果
        if ($prizeRecordAmount < $prizeSettings['number']) {
            //红包才计算分配方式，实物只有一个
            if (in_array(strtolower($typeCodes[$prizeId]), array('wechat', 'alipay'))) {
                if ($activityInfo['method'] == 0) {
                    //平均
                    $allocateAmount = floor($prizeSettings['number'] / $prizeSettings['limit']);
                } else {
                    //随机
                    if ($prizeSettings['number'] - $prizeRecordAmount <= $prizeSettings['limit']) {
                        $allocateAmount = $prizeSettings['number'] - $prizeRecordAmount;
                    } else {
                        $allocateAmount = rand(1, $prizeSettings['limit']);
                    }
                }
            } else {
                $allocateAmount = 1;
            }
            $prizeIds = array_column($activityInfo['prize'], 'id');
            $index = array_search($prizeId, $prizeIds);
            $prize = $activityInfo['prize'][$index];
            $sponsor = $this->randomSponsor($prizeId);
            //更新活动中奖纪录
            $this->activities->updateActivityRecords($activityId, array('prize_id' => $prizeId, 'number' => 1, 'amount' => $allocateAmount));
            return array('prize' => $prize, 'sponsor' => $sponsor, 'amount' => $allocateAmount);
        }
        return array();
    }

    /**
     * 根据奖品信息计算获得的奖品ID
     * @param $prizeRecords
     * @return int|string
     */
    private function randomPrize($prizeRecords)
    {
        foreach ($prizeRecords as $index => $prizeRecord) {
            $percents[$prizeRecord['prize_id']] = $prizeRecord['probability'];
        }
        if (count($percents) == 1) {
            $showPrizeId = $prizeRecords[0]['prize_id'];
        } else {
            asort($percents);
            $rangeNumber = rand(1, 100);
            if (reset($percents) == end($percents)) {
                $average = 100 / count($percents);
                if (!empty(reset($percents)) && reset($percents) <= $average) {
                    $average = reset($percents);
                }
                $default = 0;
                foreach ($percents as $prizeId => $percent) {
                    $default = $average + $default;
                    if ($rangeNumber <= $default) {
                        $showPrizeId = $prizeId;
                        break;
                    }
                }
            } else {
                $default = 0;
                foreach ($percents as $prizeId => $prizePercent) {
                    $default = $prizePercent + $default;
                    if ($rangeNumber <= $default) {
                        $showPrizeId = $prizeId;
                        break;
                    }
                }
            }
        }
        return $showPrizeId;
    }

    /**
     * 随机红包金额
     * @param $raimanAmount 剩余金额
     * @param $remainNumber 剩余个数
     * @return int
     */
    private function randomAllocate($raimanAmount, $remainNumber)
    {
        //平均取整
        $amountPerNumber = floor($raimanAmount / $remainNumber);
        //随机一个大于1小于两倍平均数的数
        $allocateAmount = rand(1, $amountPerNumber * 2);
        return $allocateAmount;
    }

    /**
     * 随机赞助商信息
     * @param $prizeInfo
     * @return array
     */
    public function randomSponsor($prizeInfo)
    {
        if (!is_array($prizeInfo)) {
            $prizeInfo = $this->activities->getPrizeInfo($prizeInfo);
        }
        $percents = array_column($prizeInfo['sponsor'], 'percent', 'id');
        if (count($percents) == 1) {
            $showSponsorId = $prizeInfo['sponsor'][0]['id'];
        } else {
            asort($percents);
            $rangeNumber = rand(1, 100);
            if (reset($percents) == end($percents)) {
                $average = floor(100 / count($percents));
                if (!empty(reset($percents)) && reset($percents) <= $average) {
                    $average = reset($percents);
                }
                $default = 0;
                foreach ($percents as $sponsorId => $percent) {
                    $default = $average + $default;
                    if ($rangeNumber <= $default) {
                        $showSponsorId = $sponsorId;
                        break;
                    }
                }
            } else {
                $default = 0;
                foreach ($percents as $sponsorId => $sponsorPercent) {
                    $default = $sponsorPercent + $default;
                    if ($rangeNumber <= $default) {
                        $showSponsorId = $sponsorId;
                        break;
                    }
                }
            }
        }
        $sponsorNames = array_column($prizeInfo['sponsor'], 'name', 'id');
        $sponsorLogos = array_column($prizeInfo['sponsor'], 'logo', 'id');
        return array('name' => $sponsorNames[$showSponsorId], 'logo' => $sponsorLogos[$showSponsorId]);
    }

    /**
     * @param $activityId
     * @return mixed
     */
    public function getActivity($activityId)
    {
        return $this->activities->findById($activityId);
    }
}
